﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography;
using SharePoint2007Migration.Attributes;
using System.Collections.Specialized;

namespace SharePoint2007Migration.Domain
{
    public class WebPartDefintion : BaseDataObject
    {
        string _typeName;
        string _assemblyName;
        Guid _webPartId;

        #region sample webpart definitions

        //<?xml version="1.0" encoding="utf-8"?>
        //<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
        //    <Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
        //    <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
        //    <Title>Web part Editor contenuto</Title>
        //    <Description>Consente di visualizzare testo formattato, tabelle e immagini.</Description>
        //    <PartImageLarge>/_layouts/images/mscontl.gif</PartImageLarge>
        //</WebPart>

        //<?xml version="1.0" encoding="utf-8" ?>
        //<webParts>
        //  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
        //    <metaData>
        //      <type name="NoobSlidesWPs.NoobSlideAdvanced, NoobSlidesWPsV2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=36b3d5906cf6944e" />
        //      <importErrorMessage>Cannot import NoobSlideAdvanced Web Part.</importErrorMessage>
        //    </metaData>
        //    <data>
        //      <properties>
        //        <property name="Title" type="string">Slide Show for Picture Library</property>
        //        <property name="Description" type="string">Genera uno slide show da allacciare ad una picture library per visualizzare immagini con effetti di mootools 1.2 </property>
        //      </properties>
        //    </data>
        //  </webPart>
        //</webParts>



        #endregion

        public WebPartDefintion(string name, XmlDocument xmlDefinition)
        {
            this.Name = name;
            this.Definition = xmlDefinition;

        }

        [DisplayProperty("WebPart name")]
        public string Name { get; private set; }

        public XmlDocument Definition { get; private set; }

        [DisplayProperty("WebPart Type name")]
        public string TypeName
        {
            get
            {
                if (_typeName == null)
                    _typeName = Get_typeName();
                return _typeName;
            }
        }

        [DisplayProperty("Assembly Name")]
        public string AssemblyName
        {
            get
            {
                if (_assemblyName == null)
                    _assemblyName = Get_assemblyName();
                return _assemblyName;
            }
        }

        [DisplayProperty("WebPart Id:")]
        public Guid WebPartId
        {
            get 
            {
                if (_webPartId.Equals(Guid.Empty))
                    _webPartId = Get_webPartId();
                return _webPartId;
            }
        }

        private string Get_assemblyName()
        {
            // should be replaced with xpath...

            XmlNamespaceManager nsManager = new XmlNamespaceManager(this.Definition.NameTable);
            XmlNodeList xnlNodeList = this.Definition.SelectNodes("/*/*/*/*", nsManager);

            // v3
            foreach (XmlNode item in xnlNodeList)
            {
                if (item.Name.ToLower() == "type")
                {
                    if (!String.IsNullOrEmpty(item.InnerText))
                    {
                        return item.InnerText;
                    }
                    else
                    {
                        XmlAttributeCollection attributes = item.Attributes;
                        foreach (XmlAttribute attr in attributes)
                        {
                            if (attr.Name.ToLower() == "name")
                                if (!String.IsNullOrEmpty(attr.Value))
                                    return attr.Value.Replace(this.TypeName+ ", ", String.Empty).Trim();
                        }
                        //return "v3 wrong!";
                    }
                }
            }

            //v2
            xnlNodeList = this.Definition.SelectNodes("/*/*", nsManager);
            foreach (XmlNode item in xnlNodeList)
            {
                if (item.Name.ToLower() == "assembly")
                {
                    if (!String.IsNullOrEmpty(item.InnerText))
                    {
                        return item.InnerText;
                    }
                    else
                    {
                        //return "v2 wrong!";
                    }
                }
            }
            throw new Exception("Unable to pars the .webpart file");
        }

        private string Get_typeName()
        {
            // should be replaced with xpath...

            XmlNamespaceManager nsManager = new XmlNamespaceManager(this.Definition.NameTable);
            XmlNodeList xnlNodeList = this.Definition.SelectNodes("/*/*/*/*", nsManager);

            // v3
            foreach (XmlNode item in xnlNodeList)
            {
                if (item.Name.ToLower() == "type")
                {
                   if (!String.IsNullOrEmpty(item.InnerText))
                    {
                        return item.InnerText;
                    }
                    else
                    {
                        XmlAttributeCollection attributes = item.Attributes;
                        foreach (XmlAttribute attr in attributes)
                        {
                            if (attr.Name.ToLower() == "name")
                                if (!String.IsNullOrEmpty(attr.Value))
                                    return attr.Value.Split(',')[0].Trim();
                        }
                       //return "v3 wrong!";
                    }
                }
            }

            //v2
            xnlNodeList = this.Definition.SelectNodes("/*/*", nsManager);
            foreach (XmlNode item in xnlNodeList)
            {
                if (item.Name.ToLower() == "typename")
                {
                    if (!String.IsNullOrEmpty(item.InnerText))
                    {
                        return item.InnerText;
                    }
                    else
                    {
                        //return "v2 wrong!";
                    }
                }
            }
            throw new Exception("Unable to pars the .webpart file");
        }

        private Guid Get_webPartId()
        {
            // thx to: http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/a0fc0978-0d55-463a-b7ab-72c00aee76a3

            string data = this.AssemblyName;
            // Will use reflection to pull up WebPart subclasses
            // but for now just use this 1 test case
            data += "|" + this.TypeName;
            byte[] dataBytes = Encoding.Unicode.GetBytes(data);
            MD5 hashAlgo = new MD5CryptoServiceProvider();
            byte[] hash = hashAlgo.ComputeHash(dataBytes);

            Guid hashGuid = new Guid(hash);
            return hashGuid;

        }


        public StringCollection GetPageUrlWhereWebPartIsInstalled(string ContentDbConnectionString)
        {
            StringCollection result = new StringCollection();
            List<Dictionary<string, object>> WebPartUrls = DataHelper.GetData(string.Format(ConfigHelper.QueryToGetMissingWpInfo,
                  this.WebPartId), ContentDbConnectionString);

            foreach (var item in WebPartUrls)
                result.Add((string)item["Url"]);
            return result;

        }

    }
}
